package LiftEngine;

import Const.ServerConst;
import java.io.Serializable;

/**
 *
 * Class description goes here.
 *
 * @author Kamil Gajowy
 */
public class Lift implements Serializable{
    private int liftDirection;
    private int currentFloor;
    private int nextFloor;
    private LiftTask task;
    private boolean traveling;
    private boolean unloadPriority = false;
    private int waiting = 0;
    private int packetId = 1;

    private int lastDoneID = -1;



    /**
    * Default constructor.
    */
    public Lift(){
        this.liftDirection = ServerConst.LiftDirectionUp;
        //TODO poprawic na BaseFloor
        this.currentFloor = 2; //ServerConst.BaseFloor;
        this.nextFloor = ServerConst.NoMoreTaskToDo;
        this.task = new LiftTask();
        this.traveling = false;
    }

    /**
     * @return the liftDirection
     */
    public int getLiftDirection() {
        return liftDirection;
    }

    /**
     * @param liftDirection the liftDirection to set
     */
    public void setLiftDirection(int liftDirection) {
        this.liftDirection = liftDirection;
    }

    /**
     * @return the currentFloor
     */
    public int getCurrentFloor() {
        return currentFloor;
    }


    /**
     * @param currentFloor the currentFloor to set
     */
    public void setCurrentFloor(int currentFloor) {
        this.currentFloor = currentFloor;
    }

    /**
     * @return the nextFloor
     */
    public int getNextFloor() {
        return nextFloor;
    }

    /**
     * @param nextFloor the nextFloor to set
     */
    public void setNextFloor(int nextFloor) {
        this.nextFloor = nextFloor;
    }

    public LiftTask getTask(){
        return this.task;
    }

    /**
     * @return the traveling
     */
    public boolean isTraveling() {
        return traveling;
    }

    /**
     * @param traveling the traveling to set
     */
    public void setTraveling(boolean traveling) {
        this.traveling = traveling;
    }

    public void updateLiftTask(){
        int i = currentFloor;
        int dir;
        int dest;
        if(liftDirection == ServerConst.LiftDirectionUp){
            dest = ServerConst.LastFloor;
            dir = 1;
        }
        else{
            dest = ServerConst.BaseFloor;
            dir = -1;
        }

        boolean choosen = false;
        if ( !isUnloadPriority() ){
            while(i!=dest){
                if (i!=currentFloor){
                if ( task.getPersonToPackOnFloorX(i) != 0 ||
                        task.getPersonToUnloadOnFloorX(i) != 0){
                    nextFloor = i;
                    choosen = true;
                    System.out.print("OK ");
                    break;
                }
                }
                i+= dir;
            }//end while
          
            if (!choosen ){
            if (i!=currentFloor){
                if (!moreLoadTaskInDir(1-liftDirection) &&
                        !moreUnloadTaskInDir(1-liftDirection)){
                    nextFloor = ServerConst.NoMoreTaskToDo;
                }
                else{
                    System.out.print("DIR ");
                      //TO REMOVE
                    //liftDirection=1-liftDirection; //TO REMOVE END
                    //updateLiftTask();
                }
            }
            }
           
            
        }else{
            //action preformed while unloading
            while(i!=dest){
                if ( task.getPersonToUnloadOnFloorX(i) != 0 ){
                    nextFloor = i;
                    choosen = true;
                    break;
                }
                i+= dir;
            }//end while

            if (!choosen ){
                if (!moreUnloadTaskInDir(1-liftDirection)){
                    nextFloor = ServerConst.NoMoreTaskToDo;
                }
                else{
                    System.out.print("DIR ");
                    //liftDirection=1-liftDirection;
                    //updateLiftTask();
                }
            }
            
        }
  

        //TODO check if unload needed !


    }//end udpate lift task

    private boolean moreLoadTaskInDir(int direction){
        int i = currentFloor;
        int dir;
        int dest;
        if(direction == ServerConst.LiftDirectionUp){
            dest = ServerConst.LastFloor;
            dir = 1;
        }
        else{
            dest = ServerConst.BaseFloor;
            dir = -1;
        }

         while(i!=dest){
            //System.out.println("\t\t  at floor " + i + "there are " + task.getPersonToPackOnFloorX(i) + " to pack");
            if ( task.getPersonToPackOnFloorX(i) != 0){
                return true;
            }
            i+= dir;
        }//end while

        return false;
    }

    private boolean moreUnloadTaskInDir(int direction){
        int i = currentFloor;
        int dir;
        int dest;
        if(direction == ServerConst.LiftDirectionUp){
            dest = ServerConst.LastFloor;
            dir = 1;
        }
        else{
            dest = ServerConst.BaseFloor;
            dir = -1;
        }

        while(i!=dest){
            //System.out.println("\t\t  at floor " + i + "there are " + task.getPersonToPackOnFloorX(i) + " to pack");
            if ( task.getPersonToUnloadOnFloorX(i) != 0){
                return true;
            }
            i+= dir;
        }//end while

        return false;
    }

    public void loadPersonFromCurrentFloor(int count) {
        System.out.println("getting " + count + " people on floor " + currentFloor);
        task.clearPersonOnFlooxX(currentFloor, count);
    }

    public boolean isUnloadPriority() {
        return this.unloadPriority;
    }

    /**
     * @return the waiting
     */
    public int isWaiting() {
        return waiting;
    }

    /**
     * @param forHowMany 
     */
    public void setWaiting(int forHowMany) {
        this.waiting = forHowMany;
    }

    /**
     * @param unloadPriority the unloadPriority to set
     */
    public void setUnloadPriority(boolean unloadPriority) {
        this.unloadPriority = unloadPriority;
    }

    public int getPacketId() {
        return packetId;
    }

    public void setPacketId(int packetId) {
        this.packetId = packetId;
    }
    public void incrementId()
    {
        setPacketId(getPacketId()+1);
    }

    /**
     * @return the lastDoneID
     */
    public int getLastDoneID() {
        return lastDoneID;
    }

    /**
     * @param lastDoneID the lastDoneID to set
     */
    public void setLastDoneID(int lastDoneID) {
        this.lastDoneID = lastDoneID;
    }

}//end class
